#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>

#include "dbsqlite.h"
#include "hbot.h"
#include "sdefs.h"

CDBSQLite::CDBSQLite(const QString &file)
{
	m_File = file;

	// Establish database connection to passed file

	m_Database = QSqlDatabase::addDatabase("QSQLITE");
	m_Database.setDatabaseName(m_File);

	if (!m_Database.open())
	{
		m_Error = "Error: Unable to establish a database connection to file [" + m_File + "]. Please be sure that the path to the file exists.";
		g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, m_Error, "SQLite", true);
		g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, m_Database.lastError().text(), "QSQLite", true);
		return;
	}

	g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Successfully established a connection to file [" + m_File + "].", "SQLite");

	// Retrieve HBot schema number

	QString hbotSV;
	QSqlQuery query;
	
	if (query.exec("SELECT version FROM config WHERE name = \"hbot_sv\""))
	{
		query.next();

		if (query.record().count() == 1)
		{
			hbotSV = query.value(0).toString();
		}
	}

	// Recreate tables if necessary

	if (hbotSV.isEmpty())
	{
		g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "[hbot_sv] not found - Assuming database is empty. Creating tables in SQLite database [" + m_File + "]", "SQLite");
		
		hbotSV = SQLITE_CURRENT_HBOT_SCHEME_VERSION;
		QSqlQuery query2;

		if (!query2.exec(SQLITE3_CREATE_TABLE_BANS))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [bans] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_GAMES))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [games] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_GAMEPLAYERS))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [gameplayers] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_DOTAGAMES))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [dotagames] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_DOTAPLAYERS))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [dotaplayers] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_USERS))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [users] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_W3MMDPLAYERS))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [w3mmdplayers] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_W3MMDVARS))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [w3mmdvars] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_SCORES))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [scores] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec("CREATE INDEX IF NOT EXISTS  idx_gameid on gameplayers (gameid)"))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create index [idx_gameid] on table [gameplayers] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec("CREATE INDEX IF NOT EXISTS idx_gameid_color on dotaplayers (gameid)"))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create index [idx_gameid_color] on table [dotaplayers] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}

		if (!query2.exec(SQLITE3_CREATE_TABLE_CONFIG))
		{
			g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create table [config] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
		}
		else
		{
			query2.prepare("INSERT INTO config VALUES (\"hbot_sv\", ?)");
			query2.bindValue(0, hbotSV);
			
			if (!query2.exec())
			{
				g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to insert [hbot_sv] version [" + hbotSV + "] in SQLite3 database [" + m_File + "] - " + query2.lastError().text() + ".", "SQLite", true);
			}
		}
	}
	else
	{
		g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Successfully found [hbot_sv] version [" + hbotSV + "].", "SQLite");
	}

	if (!query.exec("CREATE TEMPORARY TABLE iptocountry (ip1 INTEGER NOT NULL, ip2 INTEGER NOT NULL, country TEXT NOT NULL, PRIMARY KEY(ip1, ip2))"))
	{
		g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Warning: Unable to create temporary table [iptocountry] in SQLite3 database [" + m_File + "] - " + query.lastError().text() + ".", "SQLite", true);
	}
}

CDBSQLite::~CDBSQLite()
{
	g_HBot.PrintConsole(PRINT_CONSOLE_GROUP_DATABASE, "Closing SQLite3 database connection to file [" + m_File + "]", "SQLite");

	m_Database.close();
	QSqlDatabase::removeDatabase(m_Database.database().connectionName());
}
